#! /usr/bin/sdlbrt

finpr$="19_2013-06-02-220119_1280x800_scrot"
finp$=finpr$+".png"

'- from Paulo Silva, GPL license, june '10
'- captures picture from a webcam (grayscale version), converts to ZX-Spectrum .scr (.tap), and sends the .tap sound to a ZX-Spectrum via mic cable

'- dependencies:
'- sudo apt-get install fuse-emulator-utils sox imagemagick sdlbrt fswebcam
'- sudo apt-get install xawtv vgrabbj pzxtools music123 lame mpg123 sdlbasic

'- needed:
'-   a linux computer with a working webcam (like using uvcvideo) and all needed packages installed
'-   a zx-spectrum running '10 load""screen$:go to 10', and connected by audio cable to a linux computer (like on a cassette player)
'-   sdlbasic for running this code

'------

dim atmin[32,24],atmax[32,24],hb[32,24],clust[4,4],ik[32,24],pp[32,24],plte[16],zxdisp[8192],zxtap[8192]
setdisplay(768,384,32,1):paper(0x808080):ink(0):pen(0):cls

clstr$="00,06,08,14,02,12,04,10,08,14,00,06,04,10,02,12."
for y2=0 to 3:for x2=0 to 3:clust[x2,y2]=val(mid$(clstr$,((y2*4+x2)*3)+1,2)):next:next

plte[ 0]=0x000000:plte[ 1]=0x0000B4:plte[ 2]=0xB40000:plte[ 3]=0xB400B4
plte[ 4]=0x00B400:plte[ 5]=0x00B4B4:plte[ 6]=0xB4B400:plte[ 7]=0xB4B4B4
plte[ 8]=0x000000:plte[ 9]=0x0000FF:plte[10]=0xFF0000:plte[11]=0xFF00FF
plte[12]=0x00FF00:plte[13]=0x00FFFF:plte[14]=0xFFFF00:plte[15]=0xFFFFFF

function graytoprim(tlv,thb)
  tlv2=tlv
  ow=(tlv2*100)/180
  if thb<>0 then:ow=(tlv2*100)/255:end if
  'ow=0..100
  if ow<0 then:ow=0:end if
  if ow>100 then:ow=100:end if
  if ow<11 then:spw=ow/11:end if
  if ow>=11 and ow<30 then:spw=1+((ow-11)/19):end if
  if ow>=30 and ow<41 then:spw=2+((ow-30)/11):end if
  if ow>=41 and ow<59 then:spw=3+((ow-41)/18):end if
  if ow>=59 and ow<70 then:spw=4+((ow-59)/11):end if
  if ow>=70 and ow<89 then:spw=5+((ow-70)/19):end if
  if ow>=89 then:spw=6+((ow-89)/11):end if
  return spw
  end function

function grayfromclr(tprm,thb)
  tprm2=tprm
  thb2=thb
  if tprm2=0 then:tprm3=0:end if
  if tprm2=1 then:tprm3=11:end if
  if tprm2=2 then:tprm3=30:end if
  if tprm2=3 then:tprm3=41:end if
  if tprm2=4 then:tprm3=59:end if
  if tprm2=5 then:tprm3=70:end if
  if tprm2=6 then:tprm3=89:end if
  if tprm2=7 then:tprm3=100:end if
  tprm4=int((tprm3*180)/100)
  if thb=1 then:
    tprm4=int((tprm3*255)/100):end if
  return tprm4
  end function

'while 0=0

  tapln=0
  specfinp$=left$(finpr$+"          ",10)

  flsize=6912
  flsize2=flsize+2
  flsizeh=(int(flsize/256)) mod 256
  flsizel=flsize mod 256
  flsize2h=(int(flsize2/256)) mod 256
  flsize2l=flsize2 mod 256

'shell("fswebcam -d /dev/video0 _tmpr1.jpg")
'shell("convert _tmpr1.jpg -resize 256x192\\! _tmpr2.jpg")

loadimage(finp$,1):pasteicon(0,0,1)

ink(0xffffff):bar(512,0,767,191)

for y=0 to 191:for x=0to 255
  z=point(x,y)
  r0=bitwiseand(z,255):zzz=int(z/256)
  g0=bitwiseand(z,255):zzz=int(z/256)
  b0=bitwiseand(z,255)
  w0=int(((b0*11)+(r0*30)+(g0*59))/100)
  ink(rgb(w0,w0,w0))
  dot(x,y)
  next:next

for y1=0 to 23:for x1=0 to 31
  minv=255:maxv=0
  for y2=0 to 7: for x2=0 to 7
    z=point(x2+x1*8,y2+y1*8) mod 256
    if maxv<z then:
      maxv=z:atmax[x1,y1]=z
      end if
    if minv>z then:
      minv=z:atmin[x1,y1]=z
      end if
    next:next
  next:next

for y1=0 to 23:for x1=0 to 31
  hb[x1,y1]=0
  if atmax[x1,y1]>=180 then:hb[x1,y1]=1:end if
  next:next

for y1=0 to 23:for x1=0 to 31
  pp[x1,y1]=int(graytoprim(atmin[x1,y1],hb[x1,y1]))
  ik[x1,y1]=int(graytoprim(atmax[x1,y1],hb[x1,y1]))+1
  if pp[x1,y1]>6 then:pp[x1,y1]=6:end if
  if ik[x1,y1]>7 then:ik[x1,y1]=7:end if
  if ik[x1,y1]=pp[x1,y1] then:ik[x1,y1]=pp[x1,y1]+1:end if
  next:next

for y1=0 to 23:for x1=0 to 31
  ink(0xff0000)
  if hb[x1,y1]>0 then:ink(0x00ffff):end if
  bar(256+x1*8+1,192+y1*8+1,256+x1*8+5,192+y1*8+3)
  next:next

for y1=0 to 23:for x1=0 to 31
  ink(plte[pp[x1,y1]+8]):bar(512+x1*8+0,192+y1*8+0,512+x1*8+7,192+y1*8+7)
  ink(plte[ik[x1,y1]+8]):bar(512+x1*8+1,192+y1*8+1,512+x1*8+5,192+y1*8+3)
  ink(plte[pp[x1,y1]+(8*hb[x1,y1])]):bar(0+x1*8+0,192+y1*8+0,0+x1*8+7,192+y1*8+7)
  atvl=bitwiseor((ik[x1,y1]*8),pp[x1,y1])
  atvl=bitwiseor(atvl,(hb[x1,y1]*64))
  zxdisp[6144+x1+(y1*32)]=atvl
  next:next

for y1=0 to 23:for x1=0 to 31
  for y2=0 to 7:dbny=0:for x2=0 to 7
    y=(y1*8)+y2
    z=point(x2+x1*8,y2+y1*8) mod 256
    'clq=int((atmin[x1,y1])/7)*7
    'clq=atmin[x1,y1]

    clq=grayfromclr(pp[x1,y1],hb[x1,y1])



    patgf=(((clust[bitwiseand(x2,3),bitwiseand(y2,3)]+1)*255)/16)

    'if z>((atmin[x1,y1]+atmax[x1,y1])/2) then:

    'if z>(atmin[x1,y1] + ((atmax[x1,y1]-atmin[x1,y1])*(patgf/255)) ) then:
    if z>(grayfromclr(pp[x1,y1],hb[x1,y1]) + ((grayfromclr(ik[x1,y1],hb[x1,y1])-grayfromclr(pp[x1,y1],hb[x1,y1]))*(patgf/255)) ) then:


      ink(0):dot(512+x2+x1*8,y2+y1*8)
      dbny=dbny+(2^(7-x2))

      'clq=int((atmax[x1,y1])/7)*7
      'clq=atmax[x1,y1]
      clq=grayfromclr(ik[x1,y1],hb[x1,y1])


      ink(plte[ik[x1,y1]+(8*hb[x1,y1])]):dot(0+x2+x1*8,192+y2+y1*8)
      end if

    ink(rgb(clq,clq,clq))
    dot(256+x2+x1*8,y2+y1*8)

    next
    '(neded code to poke on the bitmap area - important)
    yf=bitwiseor((bitwiseand(y,7)*8),(bitwiseand(y,56)/8))
    yf=bitwiseor(yf,bitwiseand(y,192))
    zxdisp[(yf*32)+x1]=255-dbny

    next
  next:next


setcaption("saving .scr and .tap")

open finpr$+".scr" for output as #1
for i=0 to 6911
  writebyte(1,zxdisp[i])
  next
close #1

for i=0 to 9
  u=asc(mid$(specfinp$,i+1,1))
  zxtap[tapln+i+4]=u
  next

zxtap[tapln+14]=flsizel:zxtap[tapln+15]=flsizeh
zxtap[tapln+21]=flsize2l:zxtap[tapln+22]=flsize2h

checksum=0
for i=2 to 19
  checksum=bitwisexor(checksum,zxtap[tapln+i])
  next

zxtap[tapln+20]=checksum

checksum=255
for i=0 to flsize-1
  zxtap[tapln+i+24]=zxdisp[i]
  checksum=bitwisexor(checksum,zxdisp[i])
  next
zxtap[tapln+flsize+24]=checksum
tapln=tapln+(flsize+25)

zxtap[0]=19:zxtap[3]=3:zxtap[19]=128:zxtap[23]=255

open "_tmp_.tap" for output as #2
for i=0 to tapln-1
  writebyte(2,zxtap[i])
  next
close #2

'waitkey

'shell("tap2pzx _tmp_.tap | pzx2wav > _tmp_.wav")
'(using tape2wav from fuse-emulator-utils)

'setcaption("tape2wav...")
'shell("tape2wav _tmp_.tap _tmp_.wav")

'setcaption("sox play...")
'shell("play _tmp_.wav")

'wait(2000)

shell("cp _tmp_.tap "+finpr$+".tap && rm _tmp_.tap" )

'waitkey
cls
'wend


